WebSocket是瀏覽器與伺服器交換資料的方式之一,與HTTP最大的不同是,他是一個持續的雙向的連線,所以沒有重新連線,重新傳送檔頭等多餘的負荷,反應更即時。
WebSocket實際上分成兩個部分,一個是瀏覽器上的程式介面,另外一個是伺服器端的傳輸協定標準。WebSocket傳輸協定已經在今年(2012)成為IETF的正式標準:RFC 6455,從各方面來說,也已經是一個成熟的技術了。IE10、Safari6、Chrome16、Firefox11、Opera12.10等瀏覽器,也都會支援正式的標準。不過IE要到10才支援WebSocket,其他瀏覽器較舊的版本,則可能會支援不同草案版本的WebSocket。這方面可以參考Wikipedia: WebSocket。
如果不管伺服器,WebSocket在瀏覽器的使用是非常簡單的,因為他只有兩個動作:收、發。在使用前,需要建立一個WebSocket物件,把要Access的WebSocket網址傳給他:
var ws = new WebSocket('ws://127.0.0.1:8443/chat');
ws.onmessage = function(message) {alert(message.data);ws.close()};
ws.send('Hello WebSocket.');
WebSocket可以選擇ws或是wss通訊協定,ws就相當於一般的http,wss則相當於https,不過需要伺服器可以支援。其他部分使用起來,就如同一般的URL。另外,由於時持續的連線,所以在連線中URI是不會改的,所以每次也只能選擇一個URI,想跟不同URI連線,就需要建立新的WebSocket連線。
只要用send()就可以送出資料。接收資料則可以利用WebSocket的onmessage事件,資料可以透過上述程式示範中的方式取得。呼叫close()就可以結束連線。基本使用就是這樣了,真的很簡單。
除了onmessage事件,WebSocket API還支援了onopen/onclose/onerror等事件。(顧名可思義,不必多說了吧?)另外有幾個屬性可以使用,readyState就類似XMLHttpRequest的readyState,有CONNECTING/OPEN/CLOSING/CLOSED四個狀態可以查詢WebSocket目前的狀態。bufferedAmount屬性,可以取得目前有多少byte的資料尚未送出的資訊。如果傳送的資訊比較多,或是網路速度比較慢時,就可以使用他來確認前一次送出的資料到底送完沒。不過簡單的應用通常不需要擔心,因為傳送的速度應該很快。
WebSocket這個Constructor其實還有一個可省略的參數:protocol,可以指定伺服器要使用怎樣的sub protocol。例如:
var ws = new WebSocket('ws://127.0.0.1:8443/wamp', 'wamp');
另外透過protocol屬性,也可以知道目前使用的protocol(由於可以提供多個protocal給伺服器選擇,所以這個屬性)。使用sub protocol,可以把特定的應用包裝成標準的使用方法,透過支援的library,就可以不管WebSocket的運作,而專注在應用上。
目前已經有一些sub protocol應用,例如:WAMP(The Websocket Application Messaging Protocol)。不過如果不是有建立應用「標準」的需求,通常不太需要使用這個。
在伺服器方面,就比較複雜了,因為需要實作整個WebSocket Protocol...不過一般來說我們不會這樣用,而是使用支援WebSocket的Library。大致介紹一下WebSocket大致上定義了哪些東西。
首先就是交握(handshake),這其實是跟HTTP格式相容的標頭(header),裡面含有WebSocket定義的header資訊,伺服器必須處理這些資訊,然後在回應的標頭中回應處理過的結果。瀏覽器檢驗過伺服器回傳的標頭,雙方就可以建立資料連結,傳送資訊,直到呼叫close()為止。
WebSocket中資料傳送的單位叫做Frame,目前RFC 6455中定義了幾種frame:text data、binary data、ping/pong、close等,所以應該可以傳送文字跟binary資料、透過ping/pong來做heartbeat等,close則是用來做關閉連線的通知。另外,為了支援傳送未知長度的資料,frame還可以做分割以分批傳送。
這些要自己寫有點複雜,所以在伺服器端還是使用別人實作好的Library。由於伺服器端我想使用node.js,所以就選擇最多人使用的Socket.IO...這些等明天來介紹吧。
我太會喇賽的結果導致俺一天可用“討論”次數只剩下個位數,但不管剩下多少,也要在費大公這邊抛頭顱灑熱寫啦~~~
我也要
請教費大
這個WebSocket是否只能應用在實體 IP 連線
如果我是公司的內部IP 10.10.x.x
連外的IP是 74.53.124.253
WebServer 的 IP 是 118.214.231.77
如此 WebSocke 是否可以適用
一般來說應該可以,基本上他跟http是一樣的。
其實明天介紹的Socket.IO作者,有做過一些Survey:https://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software
fillanohttps://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software提到:
一般來說應該可以,基本上他跟http是一樣的。
了解
是我的問題沒問清楚
我的問題是
這個WebSocket是否如同HTTP
是由HTTP client發Request給Server然後Server回覆
有沒有
由Server主動發送資料給Client的模式
我解釋一下建立WebSocket連線的過程:
所以,連線這個動作必須要Client發起,但是之後的資訊傳輸,就沒有限制。
fillano提到:
Client可以透過這個連線送資料給Server,Server也可以透過這個連線送資料給Client,任何一方都可以透過這個連線送資料
如果是這樣的話
這應該算是重大改變了
會介紹publish subscribe嗎?
好像要用到 publish subscribe 機制的方案,
是否一定避免不了「非port 80」的情況?
這是我一直搞不清楚的。
我是沒用到pub sub pattern來做,不過基本上WebSocket是與http相容的。以node.js為例,除了Socket.IO之外,有許多WebSocket模組也都支援把WebSocket附加到http伺服器,讓同一個port(ex: 80)可以同時支援http以及WebSocket。
其實在request送達時,只要針對Request Header做過濾,就可以同時支援http跟WebSocket。差別在於,http在送出response之後就會斷線,而WebSocket在送出Response Header之後並不會斷線,除非handshake沒過,之後就透過相同的連線雙向傳送資料,直到一方斷線為止。
阿?按錯按鈕...我應該按「回應」的說
按討論也好
才會顯示有更新
原發問人才知道大師有來回覆了